1
2
3
4
5
6
7 package io.vavr;
8
9 import io.vavr.collection.*;
10 import io.vavr.control.LazyBenchmark;
11 import io.vavr.idiom.ForBenchmark;
12 import io.vavr.idiom.PatternMatchingBenchmark;
13 import io.vavr.idiom.TryBenchmark;
14 import io.vavr.idiom.TupleBenchmark;
15 import org.openjdk.jmh.annotations.Mode;
16 import org.openjdk.jmh.results.RunResult;
17 import org.openjdk.jmh.runner.Runner;
18 import org.openjdk.jmh.runner.RunnerException;
19 import org.openjdk.jmh.runner.options.ChainedOptionsBuilder;
20 import org.openjdk.jmh.runner.options.OptionsBuilder;
21 import org.openjdk.jmh.runner.options.TimeValue;
22 import org.openjdk.jmh.runner.options.VerboseMode;
23
24 import java.util.Collection;
25 import java.util.Random;
26 import java.util.concurrent.TimeUnit;
27
28 import static io.vavr.API.Array;
29
30 public class JmhRunner {
31
32
33
34
35 public static void main(String[] args) {
36 final Array<Class<?>> CLASSES = Array(
37 ArrayBenchmark.class,
38 BitSetBenchmark.class,
39 CharSeqBenchmark.class,
40 HashSetBenchmark.class,
41 ListBenchmark.class,
42 PriorityQueueBenchmark.class,
43 VectorBenchmark.class,
44
45 LazyBenchmark.class,
46
47 ForBenchmark.class,
48 PatternMatchingBenchmark.class,
49 TryBenchmark.class,
50 TupleBenchmark.class
51 );
52 runDebugWithAsserts(CLASSES);
53 runSlowNoAsserts(CLASSES);
54 }
55
56 public enum Includes {
57 JAVA("java"),
58 FUNCTIONAL_JAVA("fjava"),
59 PCOLLECTIONS("pcollections"),
60 ECOLLECTIONS("ecollections"),
61 CLOJURE("clojure"),
62 SCALAZ("scalaz"),
63 SCALA("scala"),
64 VAVR("vavr");
65
66 private final String name;
67
68 Includes(String name) { this.name = name; }
69
70 @Override
71 public String toString() { return name; }
72 }
73
74
75 public static void runDebugWithAsserts(Array<Class<?>> groups, Includes... includes) {
76 run(0, 1, 1, ForkJvm.DISABLE, VerboseMode.SILENT, Assertions.ENABLE, PrintInlining.DISABLE, groups, includes);
77 MemoryUsage.printAndReset();
78 }
79
80 @SuppressWarnings("unused")
81 public static void runQuickNoAsserts(Array<Class<?>> groups, Includes... includes) {
82 run(5, 5, 10, ForkJvm.ENABLE, VerboseMode.NORMAL, Assertions.DISABLE, PrintInlining.DISABLE, groups, includes).print();
83 }
84
85 @SuppressWarnings("unused")
86 public static void runNormalNoAsserts(Array<Class<?>> groups, Includes... includes) {
87 run(7, 7, 300, ForkJvm.ENABLE, VerboseMode.NORMAL, Assertions.DISABLE, PrintInlining.DISABLE, groups, includes).print();
88 }
89
90 @SuppressWarnings("unused")
91 public static void runSlowNoAsserts(Array<Class<?>> groups, Includes... includes) {
92 run(15, 15, 400, ForkJvm.ENABLE, VerboseMode.EXTRA, Assertions.DISABLE, PrintInlining.DISABLE, groups, includes).print();
93 }
94
95 private static BenchmarkPerformanceReporter run(int warmupIterations, int measurementIterations, int millis, ForkJvm forkJvm, VerboseMode silent, Assertions assertions, PrintInlining printInlining, Array<Class<?>> groups, Includes[] includes) {
96 final Array<String> includeNames = Array.of(includes.length == 0 ? Includes.values() : includes).map(Includes::toString);
97 final Array<String> classNames = groups.map(Class::getCanonicalName);
98 final Array<RunResult> results = run(warmupIterations, measurementIterations, millis, forkJvm, silent, assertions, printInlining, classNames, includeNames);
99 return BenchmarkPerformanceReporter.of(includeNames, classNames, results);
100 }
101
102 private static Array<RunResult> run(int warmupIterations, int measurementIterations, int millis, ForkJvm forkJvm, VerboseMode verboseMode, Assertions assertions, PrintInlining printInlining, Array<String> classNames, Array<String> includeNames) {
103 try {
104 final ChainedOptionsBuilder builder = new OptionsBuilder()
105 .shouldDoGC(true)
106 .verbosity(verboseMode)
107 .shouldFailOnError(true)
108 .mode(Mode.Throughput)
109 .timeUnit(TimeUnit.SECONDS)
110 .warmupTime(TimeValue.milliseconds(millis))
111 .warmupIterations(warmupIterations)
112 .measurementTime(TimeValue.milliseconds(millis))
113 .measurementIterations(measurementIterations)
114 .forks(forkJvm.forkCount)
115
116
117 .jvmArgsAppend("-XX:+UseG1GC", "-Xss100m", "-Xms4g", "-Xmx4g", "-XX:MaxGCPauseMillis=1000", "-XX:+UnlockExperimentalVMOptions", "-XX:G1NewSizePercent=100", "-XX:G1MaxNewSizePercent=100", assertions.vmArg);
118
119 final String includePattern = includeNames.mkString("\\..*?\\b(", "|", ")_");
120 classNames.forEach(name -> builder.include(name + includePattern));
121
122 if (printInlining == PrintInlining.ENABLE) {
123 builder.jvmArgsAppend("-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining");
124 }
125
126 return Array.ofAll(new Runner(builder.build()).run());
127 } catch (RunnerException e) {
128 throw new RuntimeException(e);
129 }
130 }
131
132
133 private enum ForkJvm {
134 ENABLE(1),
135 DISABLE(0);
136
137 final int forkCount;
138
139 ForkJvm(int forkCount) {
140 this.forkCount = forkCount;
141 }
142 }
143
144 private enum Assertions {
145 ENABLE("-enableassertions"),
146 DISABLE("-disableassertions");
147
148 final String vmArg;
149
150 Assertions(String vmArg) {
151 this.vmArg = vmArg;
152 }
153 }
154
155 private enum PrintInlining {
156 ENABLE,
157 DISABLE;
158 }
159
160
161
162 public static Integer[] getRandomValues(int size, int seed) {
163 return getRandomValues(size, seed, false);
164 }
165
166 public static Integer[] getRandomValues(int size, int seed, boolean nonNegative) {
167 return getRandomValues(size, nonNegative, new Random(seed));
168 }
169
170 public static Integer[] getRandomValues(int size, boolean nonNegative, Random random) {
171 final Integer[] results = new Integer[size];
172 for (int i = 0; i < size; i++) {
173 final int value = random.nextInt(size) - (nonNegative ? 0 : (size / 2));
174 results[i] = value;
175 }
176 return results;
177 }
178
179
180 public static <T> int[] shuffle(int[] array, Random random) {
181 for (int i = array.length; i > 1; i--) {
182 swap(array, i - 1, random.nextInt(i));
183 }
184 return array;
185 }
186
187 static <T> void swap(int[] array, int i, int j) {
188 final int temp = array[i];
189 array[i] = array[j];
190 array[j] = temp;
191 }
192
193
194 public static int aggregate(int x, int y) {
195 return x ^ y;
196 }
197
198
199 public static <T extends Collection<?>, R> R create(Function1<T, R> function, T source, Function1<R, Boolean> assertion) {
200 return create(function, source, source.size(), assertion);
201 }
202
203 @SuppressWarnings("unchecked")
204 public static <T, R> R create(Function1<T, R> function, T source, int elementCount, Function1<R, Boolean> assertion) {
205 final R result = function.apply(source);
206 assert assertion.apply(result);
207
208 MemoryUsage.storeMemoryUsages(elementCount, result);
209
210 return result;
211 }
212 }